// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <PyDatabaseCorrelation.h>
#include <ObserverToCallback.h>
#include <stdio.h>
#include <Py2and3Support.h>

// ****************************************************************************
// Module: PyDatabaseCorrelation
//
// Purpose:
//   This class encapsulates a database correlation, which is a mapping of one or more databases to a set of indices that go from 0 to N.
//
// Note:       Autogenerated by xml2python. Do not modify by hand!
//
// Programmer: xml2python
// Creation:   omitted
//
// ****************************************************************************

//
// This struct contains the Python type information and a DatabaseCorrelation.
//
struct DatabaseCorrelationObject
{
    PyObject_HEAD
    DatabaseCorrelation *data;
    bool        owns;
    PyObject   *parent;
};

//
// Internal prototypes
//
static PyObject *NewDatabaseCorrelation(int);

///////////////////////////////////////////////////////////////////////////////
/// Custom PyDatabaseCorrelation_ToString
///////////////////////////////////////////////////////////////////////////////


std::string
PyDatabaseCorrelation_ToString(const DatabaseCorrelation *atts, const char *prefix)
{
    std::string str;
    char tmpStr[1000];

    // Make a reference.
    const DatabaseCorrelation &correlation = *atts;

    snprintf(tmpStr, 1000, "name = \"%s\"\n", atts->GetName().c_str());
    str += tmpStr;
    snprintf(tmpStr, 1000, "numStates = %d\n", atts->GetNumStates());
    str += tmpStr;
    const char *method_names = "IndexForIndexCorrelation, StretchedIndexCorrelation, TimeCorrelation, CycleCorrelation, UserDefinedCorrelation";
    if(atts->GetMethod() == DatabaseCorrelation::IndexForIndexCorrelation)
        {
             snprintf(tmpStr, 1000, "method = IndexForIndexCorrelation  # %s\n", method_names);
             str += tmpStr;
        }
    else if(atts->GetMethod() == DatabaseCorrelation::StretchedIndexCorrelation)
        {
             snprintf(tmpStr, 1000, "method = StretchedIndexCorrelation  # %s\n", method_names);
             str += tmpStr;
        }
    else if(atts->GetMethod() == DatabaseCorrelation::TimeCorrelation)
        {
             snprintf(tmpStr, 1000, "method = TimeCorrelation  # %s\n", method_names);
             str += tmpStr;
        }
    else if(atts->GetMethod() == DatabaseCorrelation::CycleCorrelation)
        {
             snprintf(tmpStr, 1000, "method = CycleCorrelation  # %s\n", method_names);
             str += tmpStr;
        }
    else
        {
             snprintf(tmpStr, 1000, "method = UserDefinedCorrelation  # %s\n", method_names);
             str += tmpStr;
        }

    size_t i, j, index = 0;
    const stringVector &databaseNames = correlation.GetDatabaseNames();
    for(i = 0; i < databaseNames.size(); ++i)
    {
        snprintf(tmpStr, 1000, "database[%ld]=%s\n", i, databaseNames[i].c_str());
        str += tmpStr;
        snprintf(tmpStr, 1000, "    numStates=%d\n", correlation.GetDatabaseNStates()[i]);
        str += tmpStr;
        str += "    times={";
        for(j = 0; j < (size_t)correlation.GetDatabaseNStates()[i]; ++j)
        {
            snprintf(tmpStr, 1000, "%g, ", correlation.GetDatabaseTimes()[index+j]);
            str += tmpStr;
        }
        str += "}\n";
        str += "    cycles={";
        for(j = 0; j < (size_t)correlation.GetDatabaseNStates()[i]; ++j)
        {
            snprintf(tmpStr, 1000, "%d, ", correlation.GetDatabaseCycles()[index+j]);
            str += tmpStr;
        }
        str += "}\n";

        index += correlation.GetDatabaseNStates()[i];

        str += "    indices={";
        for(j = 0; j < (size_t)correlation.GetNumStates(); ++j)
        {
            snprintf(tmpStr, 1000, "%d, ", correlation.GetIndices()[i*correlation.GetNumStates() + j]);
            str += tmpStr;
        }
        str += "}\n";
    }

    {   const doubleVector &condensedTimes = atts->GetCondensedTimes();
        snprintf(tmpStr, 1000, "condensedTimes = (");
        str += tmpStr;
        for(i = 0; i < condensedTimes.size(); ++i)
        {
            snprintf(tmpStr, 1000, "%g", condensedTimes[i]);
            str += tmpStr;
            if(i < condensedTimes.size() - 1)
            {
                snprintf(tmpStr, 1000, ", ");
                str += tmpStr;
            }
        }
        snprintf(tmpStr, 1000, ")\n");
        str += tmpStr;
    }
    {   const intVector &condensedCycles = atts->GetCondensedCycles();
        snprintf(tmpStr, 1000, "condensedCycles = (");
        str += tmpStr;
        for(i = 0; i < condensedCycles.size(); ++i)
        {
            snprintf(tmpStr, 1000, "%d", condensedCycles[i]);
            str += tmpStr;
            if(i < condensedCycles.size() - 1)
            {
                snprintf(tmpStr, 1000, ", ");
                str += tmpStr;
            }
        }
        snprintf(tmpStr, 1000, ")\n");
        str += tmpStr;
    }
    return str;
}


// std::string
// PyDatabaseCorrelation_ToString(const DatabaseCorrelation *atts, const char *prefix)
// {
//     std::string str;
//     char tmpStr[1000];
//
//     snprintf(tmpStr, 1000, "%sname = \"%s\"\n", prefix, atts->GetName().c_str());
//     str += tmpStr;
//     snprintf(tmpStr, 1000, "%snumStates = %d\n", prefix, atts->GetNumStates());
//     str += tmpStr;
//     const char *method_names = "IndexForIndexCorrelation, StretchedIndexCorrelation, TimeCorrelation, CycleCorrelation, UserDefinedCorrelation";
//     switch (atts->GetMethod())
//     {
//       case DatabaseCorrelation::IndexForIndexCorrelation:
//           snprintf(tmpStr, 1000, "%smethod = %sIndexForIndexCorrelation  # %s\n", prefix, prefix, method_names);
//           str += tmpStr;
//           break;
//       case DatabaseCorrelation::StretchedIndexCorrelation:
//           snprintf(tmpStr, 1000, "%smethod = %sStretchedIndexCorrelation  # %s\n", prefix, prefix, method_names);
//           str += tmpStr;
//           break;
//       case DatabaseCorrelation::TimeCorrelation:
//           snprintf(tmpStr, 1000, "%smethod = %sTimeCorrelation  # %s\n", prefix, prefix, method_names);
//           str += tmpStr;
//           break;
//       case DatabaseCorrelation::CycleCorrelation:
//           snprintf(tmpStr, 1000, "%smethod = %sCycleCorrelation  # %s\n", prefix, prefix, method_names);
//           str += tmpStr;
//           break;
//       case DatabaseCorrelation::UserDefinedCorrelation:
//           snprintf(tmpStr, 1000, "%smethod = %sUserDefinedCorrelation  # %s\n", prefix, prefix, method_names);
//           str += tmpStr;
//           break;
//       default:
//           break;
//     }
//
//     {   const stringVector &databaseNames = atts->GetDatabaseNames();
//         snprintf(tmpStr, 1000, "%sdatabaseNames = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < databaseNames.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "\"%s\"", databaseNames[i].c_str());
//             str += tmpStr;
//             if(i < databaseNames.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const intVector &databaseNStates = atts->GetDatabaseNStates();
//         snprintf(tmpStr, 1000, "%sdatabaseNStates = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < databaseNStates.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%d", databaseNStates[i]);
//             str += tmpStr;
//             if(i < databaseNStates.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const doubleVector &databaseTimes = atts->GetDatabaseTimes();
//         snprintf(tmpStr, 1000, "%sdatabaseTimes = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < databaseTimes.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%g", databaseTimes[i]);
//             str += tmpStr;
//             if(i < databaseTimes.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const intVector &databaseCycles = atts->GetDatabaseCycles();
//         snprintf(tmpStr, 1000, "%sdatabaseCycles = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < databaseCycles.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%d", databaseCycles[i]);
//             str += tmpStr;
//             if(i < databaseCycles.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const intVector &indices = atts->GetIndices();
//         snprintf(tmpStr, 1000, "%sindices = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < indices.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%d", indices[i]);
//             str += tmpStr;
//             if(i < indices.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const doubleVector &condensedTimes = atts->GetCondensedTimes();
//         snprintf(tmpStr, 1000, "%scondensedTimes = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < condensedTimes.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%g", condensedTimes[i]);
//             str += tmpStr;
//             if(i < condensedTimes.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     {   const intVector &condensedCycles = atts->GetCondensedCycles();
//         snprintf(tmpStr, 1000, "%scondensedCycles = (", prefix);
//         str += tmpStr;
//         for(size_t i = 0; i < condensedCycles.size(); ++i)
//         {
//             snprintf(tmpStr, 1000, "%d", condensedCycles[i]);
//             str += tmpStr;
//             if(i < condensedCycles.size() - 1)
//             {
//                 snprintf(tmpStr, 1000, ", ");
//                 str += tmpStr;
//             }
//         }
//         snprintf(tmpStr, 1000, ")\n");
//         str += tmpStr;
//     }
//     return str;
// }

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_Notify
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetName
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetName(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    PyObject *retval = PyString_FromString(obj->data->GetName().c_str());
    return retval;
}


///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetNumStates
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetNumStates(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    PyObject *retval = PyInt_FromLong(long(obj->data->GetNumStates()));
    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetMethod
///////////////////////////////////////////////////////////////////////////////


/*static*/ PyObject *
DatabaseCorrelation_GetMethod(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    PyObject *retval = PyInt_FromLong(long(obj->data->GetMethod()));
    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetDatabaseNames
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetDatabaseNames(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the databaseNames.
    const stringVector &databaseNames = obj->data->GetDatabaseNames();
    PyObject *retval = PyTuple_New(databaseNames.size());
    for(size_t i = 0; i < databaseNames.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyString_FromString(databaseNames[i].c_str()));
    return retval;
}


///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetDatabaseNStates
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetDatabaseNStates(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the databaseNStates.
    const intVector &databaseNStates = obj->data->GetDatabaseNStates();
    PyObject *retval = PyTuple_New(databaseNStates.size());
    for(size_t i = 0; i < databaseNStates.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyInt_FromLong(long(databaseNStates[i])));
    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetDatabaseTimes
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetDatabaseTimes(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the databaseTimes.
    const doubleVector &databaseTimes = obj->data->GetDatabaseTimes();
    PyObject *retval = PyTuple_New(databaseTimes.size());
    for(size_t i = 0; i < databaseTimes.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyFloat_FromDouble(databaseTimes[i]));
    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetDatabaseCycles
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetDatabaseCycles(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the databaseCycles.
    const intVector &databaseCycles = obj->data->GetDatabaseCycles();
    PyObject *retval = PyTuple_New(databaseCycles.size());
    for(size_t i = 0; i < databaseCycles.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyInt_FromLong(long(databaseCycles[i])));
    return retval;
}


///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetIndices
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetIndices(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the indices.
    const intVector &indices = obj->data->GetIndices();
    PyObject *retval = PyTuple_New(indices.size());
    for(size_t i = 0; i < indices.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyInt_FromLong(long(indices[i])));
    return retval;
}


///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetCondensedTimes
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetCondensedTimes(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the condensedTimes.
    const doubleVector &condensedTimes = obj->data->GetCondensedTimes();
    PyObject *retval = PyTuple_New(condensedTimes.size());
    for(size_t i = 0; i < condensedTimes.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyFloat_FromDouble(condensedTimes[i]));
    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// REMOVED  DatabaseCorrelation_SetCondensedCycles
///////////////////////////////////////////////////////////////////////////////

/*static*/ PyObject *
DatabaseCorrelation_GetCondensedCycles(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    // Allocate a tuple the with enough entries to hold the condensedCycles.
    const intVector &condensedCycles = obj->data->GetCondensedCycles();
    PyObject *retval = PyTuple_New(condensedCycles.size());
    for(size_t i = 0; i < condensedCycles.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyInt_FromLong(long(condensedCycles[i])));
    return retval;
}



////////////////////////////////////////////////////////////////////////////////
/// NOTE THAT ALL SET METHODS AND MANY GET METHODS WERE REMOVED
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// BEGIN WRAPPED USER-DEFINED DATABASECORRELATION METHODS.
////////////////////////////////////////////////////////////////////////////////

static PyObject *
DatabaseCorrelation_GetCorrelatedTimeStates(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;

    int state = 0;
    if (!PyArg_ParseTuple(args, "i", &state))
        return NULL;

    PyObject *retval = 0;
    intVector states;
    if(obj->data->GetCorrelatedTimeStates(state, states))
    {
        // Allocate a tuple the with enough entries to hold the correlated
        // time states.
        retval = PyTuple_New(states.size());
        for(size_t i = 0; i < states.size(); ++i)
        PyTuple_SET_ITEM(retval, i, PyLong_FromLong(states[i]));
    }
    else
        retval = PyTuple_New(0);

    return retval;
}

static PyObject *
DatabaseCorrelation_UsesDatabase(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    char *name = 0;
    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;

    bool val = obj->data->UsesDatabase(name);
    return PyLong_FromLong(long(val ? 1 : 0));
}

static PyObject *
DatabaseCorrelation_GetNumDatabases(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    return PyLong_FromLong(long(obj->data->GetNumDatabases()));
}

static PyObject *
DatabaseCorrelation_GetCorrelatedTimeState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    char *db = 0;
    int state = 0;
    if (!PyArg_ParseTuple(args, "si", &db, &state))
        return NULL;

    return PyLong_FromLong(long(obj->data->GetCorrelatedTimeState(db, state)));
}

static PyObject *
DatabaseCorrelation_GetInverseCorrelatedTimeState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    char *db = 0;
    int state = 0;
    if (!PyArg_ParseTuple(args, "si", &db, &state))
        return NULL;

    return PyLong_FromLong(long(obj->data->GetInverseCorrelatedTimeState(db, state)));
}

static PyObject *
DatabaseCorrelation_GetDatabaseCycleForState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    char *db = 0;
    int state = 0;
    if (!PyArg_ParseTuple(args, "si", &db, &state))
        return NULL;

    const intVector &cycles = obj->data->GetDatabaseCycles();
    const stringVector &databaseNames = obj->data->GetDatabaseNames();
    const intVector &nStates = obj->data->GetDatabaseNStates();
    int retval = -1;
    int index = 0;
    if(state >= 0)
    {
        for(size_t i = 0; i < databaseNames.size(); ++i)
        {
            if(databaseNames[i] == db)
            {
                if(state < nStates[i])
                    retval = cycles[index + state];
                break;
            }
            index += nStates[i];
        }
    }

    return PyLong_FromLong(long(retval));
}

static PyObject *
DatabaseCorrelation_GetDatabaseTimeForState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    char *db = 0;
    int state = 0;
    if (!PyArg_ParseTuple(args, "si", &db, &state))
        return NULL;

    const doubleVector &times = obj->data->GetDatabaseTimes();
    const stringVector &databaseNames = obj->data->GetDatabaseNames();
    const intVector &nStates = obj->data->GetDatabaseNStates();
    double retval = 0.;
    int index = 0;
    if(state >= 0)
    {
        for(size_t i = 0; i < databaseNames.size(); ++i)
        {
            if(databaseNames[i] == db)
            {
                if(state < nStates[i])
                    retval = times[index + state];
                break;
            }
            index += nStates[i];
        }
    }

    return PyFloat_FromDouble(retval);
}

static PyObject *
DatabaseCorrelation_GetCondensedCycleForState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    int state = 0;
    if (!PyArg_ParseTuple(args, "i", &state))
        return NULL;

    return PyLong_FromLong(long(obj->data->GetCondensedCycleForState(state)));
}

static PyObject *
DatabaseCorrelation_GetCondensedTimeForState(PyObject *self, PyObject *args)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)self;
    int state = 0;
    if (!PyArg_ParseTuple(args, "i", &state))
        return NULL;

    return PyFloat_FromDouble(obj->data->GetCondensedTimeForState(state));
}

////////////////////////////////////////////////////////////////////////////////
/// END WRAPPED USER-DEFINED DATABASECORRELATION METHODS.
////////////////////////////////////////////////////////////////////////////////


static struct PyMethodDef DatabaseCorrelation_methods[] = {
    {"GetName", DatabaseCorrelation_GetName, METH_VARARGS},
    {"GetNumStates", DatabaseCorrelation_GetNumStates, METH_VARARGS},
    {"GetMethod", DatabaseCorrelation_GetMethod, METH_VARARGS},
    {"GetDatabaseNames", DatabaseCorrelation_GetDatabaseNames, METH_VARARGS},
    {"GetDatabaseNStates", DatabaseCorrelation_GetDatabaseNStates, METH_VARARGS},

    //
    // User-defined functions that we've wrapped.
    //
    {"GetCorrelatedTimeStates", DatabaseCorrelation_GetCorrelatedTimeStates, METH_VARARGS},
    {"UsesDatabase", DatabaseCorrelation_UsesDatabase, METH_VARARGS},
    {"GetNumDatabases", DatabaseCorrelation_GetNumDatabases, METH_VARARGS},
    {"GetCorrelatedTimeState", DatabaseCorrelation_GetCorrelatedTimeState, METH_VARARGS},
    {"GetInverseCorrelatedTimeState", DatabaseCorrelation_GetInverseCorrelatedTimeState, METH_VARARGS},
    {"GetDatabaseCycleForState", DatabaseCorrelation_GetDatabaseCycleForState, METH_VARARGS},
    {"GetDatabaseTimeForState", DatabaseCorrelation_GetDatabaseTimeForState, METH_VARARGS},
    {"GetCondensedCycleForState", DatabaseCorrelation_GetCondensedCycleForState, METH_VARARGS},
    {"GetCondensedTimeForState", DatabaseCorrelation_GetCondensedTimeForState, METH_VARARGS},
    {NULL, NULL}
};

//
// Type functions
//

static void
DatabaseCorrelation_dealloc(PyObject *v)
{
   DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)v;
   if(obj->parent != 0)
       Py_DECREF(obj->parent);
   if(obj->owns)
       delete obj->data;
}

static PyObject *DatabaseCorrelation_richcompare(PyObject *self, PyObject *other, int op);

///////////////////////////////////////////////////////////////////////////////
/// Custom PyDatabaseCorrelation_getattr
///////////////////////////////////////////////////////////////////////////////


PyObject *
PyDatabaseCorrelation_getattr(PyObject *self, char *name)
{
    if(strcmp(name, "name") == 0)
        return DatabaseCorrelation_GetName(self, NULL);
    if(strcmp(name, "numStates") == 0)
        return DatabaseCorrelation_GetNumStates(self, NULL);
    if(strcmp(name, "method") == 0)
        return DatabaseCorrelation_GetMethod(self, NULL);
    if(strcmp(name, "IndexForIndexCorrelation") == 0)
        return PyInt_FromLong(long(DatabaseCorrelation::IndexForIndexCorrelation));
    else if(strcmp(name, "StretchedIndexCorrelation") == 0)
        return PyInt_FromLong(long(DatabaseCorrelation::StretchedIndexCorrelation));
    else if(strcmp(name, "TimeCorrelation") == 0)
        return PyInt_FromLong(long(DatabaseCorrelation::TimeCorrelation));
    else if(strcmp(name, "CycleCorrelation") == 0)
        return PyInt_FromLong(long(DatabaseCorrelation::CycleCorrelation));
    else if(strcmp(name, "UserDefinedCorrelation") == 0)
        return PyInt_FromLong(long(DatabaseCorrelation::UserDefinedCorrelation));

    if(strcmp(name, "databaseNames") == 0)
        return DatabaseCorrelation_GetDatabaseNames(self, NULL);
    if(strcmp(name, "databaseNStates") == 0)
        return DatabaseCorrelation_GetDatabaseNStates(self, NULL);

    return Py_FindMethod(DatabaseCorrelation_methods, self, name);
}


///////////////////////////////////////////////////////////////////////////////
/// Custom PyDatabaseCorrelation_setattr
///////////////////////////////////////////////////////////////////////////////

int
PyDatabaseCorrelation_setattr(PyObject *self, char *name, PyObject *args)
{
    return -1;
}

static int
DatabaseCorrelation_print(PyObject *v, FILE *fp, int flags)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)v;
    fprintf(fp, "%s", PyDatabaseCorrelation_ToString(obj->data, "").c_str());
    return 0;
}

PyObject *
DatabaseCorrelation_str(PyObject *v)
{
    DatabaseCorrelationObject *obj = (DatabaseCorrelationObject *)v;
    return PyString_FromString(PyDatabaseCorrelation_ToString(obj->data,"").c_str());
}

//
// The doc string for the class.
//
#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 5)
static const char *DatabaseCorrelation_Purpose = "This class encapsulates a database correlation, which is a mapping of one or more databases to a set of indices that go from 0 to N.";
#else
static char *DatabaseCorrelation_Purpose = "This class encapsulates a database correlation, which is a mapping of one or more databases to a set of indices that go from 0 to N.";
#endif

//
// Python Type Struct Def Macro from Py2and3Support.h
//
//         VISIT_PY_TYPE_OBJ( VPY_TYPE,
//                            VPY_NAME,
//                            VPY_OBJECT,
//                            VPY_DEALLOC,
//                            VPY_PRINT,
//                            VPY_GETATTR,
//                            VPY_SETATTR,
//                            VPY_STR,
//                            VPY_PURPOSE,
//                            VPY_RICHCOMP,
//                            VPY_AS_NUMBER)

//
// The type description structure
//

VISIT_PY_TYPE_OBJ(DatabaseCorrelationType,         \
                  "DatabaseCorrelation",           \
                  DatabaseCorrelationObject,       \
                  DatabaseCorrelation_dealloc,     \
                  DatabaseCorrelation_print,       \
                  PyDatabaseCorrelation_getattr,   \
                  PyDatabaseCorrelation_setattr,   \
                  DatabaseCorrelation_str,         \
                  DatabaseCorrelation_Purpose,     \
                  DatabaseCorrelation_richcompare, \
                  0); /* as_number*/

//
// Helper function for comparing.
//
static PyObject *
DatabaseCorrelation_richcompare(PyObject *self, PyObject *other, int op)
{
    // only compare against the same type 
    if ( Py_TYPE(self) == Py_TYPE(other) 
         && Py_TYPE(self) == &DatabaseCorrelationType)
    {
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *res = NULL;
    DatabaseCorrelation *a = ((DatabaseCorrelationObject *)self)->data;
    DatabaseCorrelation *b = ((DatabaseCorrelationObject *)other)->data;

    switch (op)
    {
       case Py_EQ:
           res = (*a == *b) ? Py_True : Py_False;
           break;
       case Py_NE:
           res = (*a != *b) ? Py_True : Py_False;
           break;
       default:
           res = Py_NotImplemented;
           break;
    }

    Py_INCREF(res);
    return res;
}

//
// Helper functions for object allocation.
//

static DatabaseCorrelation *defaultAtts = 0;
static DatabaseCorrelation *currentAtts = 0;

static PyObject *
NewDatabaseCorrelation(int useCurrent)
{
    DatabaseCorrelationObject *newObject;
    newObject = PyObject_NEW(DatabaseCorrelationObject, &DatabaseCorrelationType);
    if(newObject == NULL)
        return NULL;
    if(useCurrent && currentAtts != 0)
        newObject->data = new DatabaseCorrelation(*currentAtts);
    else if(defaultAtts != 0)
        newObject->data = new DatabaseCorrelation(*defaultAtts);
    else
        newObject->data = new DatabaseCorrelation;
    newObject->owns = true;
    newObject->parent = 0;
    return (PyObject *)newObject;
}

static PyObject *
WrapDatabaseCorrelation(const DatabaseCorrelation *attr)
{
    DatabaseCorrelationObject *newObject;
    newObject = PyObject_NEW(DatabaseCorrelationObject, &DatabaseCorrelationType);
    if(newObject == NULL)
        return NULL;
    newObject->data = (DatabaseCorrelation *)attr;
    newObject->owns = false;
    newObject->parent = 0;
    return (PyObject *)newObject;
}

///////////////////////////////////////////////////////////////////////////////
//
// Interface that is exposed to the VisIt module.
//
///////////////////////////////////////////////////////////////////////////////

PyObject *
DatabaseCorrelation_new(PyObject *self, PyObject *args)
{
    int useCurrent = 0;
    if (!PyArg_ParseTuple(args, "i", &useCurrent))
    {
        if (!PyArg_ParseTuple(args, ""))
            return NULL;
        else
            PyErr_Clear();
    }

    return (PyObject *)NewDatabaseCorrelation(useCurrent);
}

//
// Plugin method table. These methods are added to the visitmodule's methods.
//
static PyMethodDef DatabaseCorrelationMethods[] = {
    {"DatabaseCorrelation", DatabaseCorrelation_new, METH_VARARGS},
    {NULL,      NULL}        /* Sentinel */
};

static Observer *DatabaseCorrelationObserver = 0;

std::string
PyDatabaseCorrelation_GetLogString()
{
    std::string s("DatabaseCorrelation = DatabaseCorrelation()\n");
    if(currentAtts != 0)
        s += PyDatabaseCorrelation_ToString(currentAtts, "DatabaseCorrelation.");
    return s;
}

static void
PyDatabaseCorrelation_CallLogRoutine(Subject *subj, void *data)
{
    typedef void (*logCallback)(const std::string &);
    logCallback cb = (logCallback)data;

    if(cb != 0)
    {
        std::string s("DatabaseCorrelation = DatabaseCorrelation()\n");
        s += PyDatabaseCorrelation_ToString(currentAtts, "DatabaseCorrelation.");
        cb(s);
    }
}

void
PyDatabaseCorrelation_StartUp(DatabaseCorrelation *subj, void *data)
{
    if(subj == 0)
        return;

    currentAtts = subj;
    PyDatabaseCorrelation_SetDefaults(subj);

    //
    // Create the observer that will be notified when the attributes change.
    //
    if(DatabaseCorrelationObserver == 0)
    {
        DatabaseCorrelationObserver = new ObserverToCallback(subj,
            PyDatabaseCorrelation_CallLogRoutine, (void *)data);
    }

}

void
PyDatabaseCorrelation_CloseDown()
{
    delete defaultAtts;
    defaultAtts = 0;
    delete DatabaseCorrelationObserver;
    DatabaseCorrelationObserver = 0;
}

PyMethodDef *
PyDatabaseCorrelation_GetMethodTable(int *nMethods)
{
    *nMethods = 1;
    return DatabaseCorrelationMethods;
}

bool
PyDatabaseCorrelation_Check(PyObject *obj)
{
    return (obj->ob_type == &DatabaseCorrelationType);
}

DatabaseCorrelation *
PyDatabaseCorrelation_FromPyObject(PyObject *obj)
{
    DatabaseCorrelationObject *obj2 = (DatabaseCorrelationObject *)obj;
    return obj2->data;
}

PyObject *
PyDatabaseCorrelation_New()
{
    return NewDatabaseCorrelation(0);
}

PyObject *
PyDatabaseCorrelation_Wrap(const DatabaseCorrelation *attr)
{
    return WrapDatabaseCorrelation(attr);
}

void
PyDatabaseCorrelation_SetParent(PyObject *obj, PyObject *parent)
{
    DatabaseCorrelationObject *obj2 = (DatabaseCorrelationObject *)obj;
    obj2->parent = parent;
}

void
PyDatabaseCorrelation_SetDefaults(const DatabaseCorrelation *atts)
{
    if(defaultAtts)
        delete defaultAtts;

    defaultAtts = new DatabaseCorrelation(*atts);
}

